package com.demo.example.impl;

import com.alibaba.fastjson2.JSON;
import com.demo.example.RestHighLevelClientExample;
import com.demo.model.entity.Book;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.xcontent.XContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author shenguangyang
 */
@Service
public class RestHighLevelClientExampleImpl implements RestHighLevelClientExample {
    private static final Logger log = LoggerFactory.getLogger(RestHighLevelClientExampleImpl.class);

    @Resource
    public RestHighLevelClient client;

    @Resource
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public void createIndex(String indexName) throws IOException {
        System.out.println("=======================================>>> createIndex");
        CreateIndexRequest request = new CreateIndexRequest(indexName);
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
        // 查看是否创建成功
        System.out.println(response.isAcknowledged());
        // 查看返回对象
        System.out.println(response);
    }

    @Override
    public void indexIsExists(String indexName) throws IOException {
        System.out.println("=======================================>>> indexIsExists");
        GetIndexRequest request = new GetIndexRequest(indexName);
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println(exists); // 索引是否存在
    }

    @Override
    public void deleteIndex(String indexName) throws IOException {
        System.out.println("=======================================>>> deleteIndex");
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
        AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
        System.out.println(response.isAcknowledged());// 是否删除成功
    }

    @Override
    public void saveDocument(String indexName, Book book) throws IOException {
        System.out.println("=======================================>>> saveDocument");

        // 创建请求
        IndexRequest request = new IndexRequest(indexName);
        // 制定规则 PUT /{indexName}/_doc/1
        request.id(book.getId());// 设置文档ID
        request.timeout(TimeValue.timeValueMillis(1000));// request.timeout("1s")
        // 将我们的数据放入请求中
        request.source(JSON.toJSONString(book), XContentType.JSON);
        // 客户端发送请求，获取响应的结果
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        System.out.println(response.status());// 获取建立索引的状态信息 CREATED
        System.out.println(response);// 查看返回内容 IndexResponse[index=liuyou_index,type=_doc,id=1,version=1,result=created,seqNo=0,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
    }

    @Override
    public void isExistDocument(String indexName, String id) throws IOException {
        GetRequest request = new GetRequest(indexName, id);
        // 不获取返回的 _source 的上下文了
        request.fetchSourceContext(new FetchSourceContext(false));
        request.storedFields("_none_");
        boolean exists = client.exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

    @Override
    public void getDocumentById(String indexName, String id) throws IOException {
        GetRequest request = new GetRequest(indexName, id);
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        System.out.println(response.getSourceAsString());// 打印文档内容
        System.out.println(request);// 返回的全部内容和命令是一样的
    }

    @Override
    public void updateDocumentById(String indexName, Book book) throws IOException {
        UpdateRequest request = new UpdateRequest(indexName, book.getId());
        request.doc(JSON.toJSONString(book),XContentType.JSON);
        UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
        System.out.println(response.status()); // OK
    }

    @Override
    public void deleteDocumentById(String indexName,  String id) throws IOException {
        DeleteRequest request = new DeleteRequest(indexName, id);
        request.timeout("1s");
        DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
        System.out.println(response.status());// OK
    }

    @Override
    public void saveDocumentBatch(String indexName, List<Book> books) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");

        // 批量请求处理
        for (Book book : books) {
            bulkRequest.add(
                    // 这里是数据信息
                    new IndexRequest(indexName)
                            .id(book.getId()) // 没有设置id 会自定生成一个随机id
                            .source(JSON.toJSONString(book), XContentType.JSON)
            );
        }
        BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulk.status());// ok
    }

    @Override
    public void searchDocument(String indexName, String keyword) throws IOException {
        int page = 0;
        int size = 5;
        // 1.创建查询请求对象
        SearchRequest searchRequest = new SearchRequest(indexName);
        // 2. 构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 查询条件 使用QueryBuilders工具类创建
        // 精确查询
        // TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("sales", "1");

        // 多字段匹配查询
        MatchQueryBuilder titleMatch = QueryBuilders.matchQuery("name", keyword).boost(1.0f);
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.should(titleMatch);
        MatchQueryBuilder contentTextMatch = QueryBuilders.matchQuery("content", keyword).boost(1.0f);
        boolQueryBuilder.should(contentTextMatch);

        // 匹配查询
        //  MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();

        // 设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name").field("content").preTags("<span style=\"color:red\">").postTags("</span>");
        searchSourceBuilder.highlighter(highlightBuilder);
        // 分页
        searchSourceBuilder.from(page);
        searchSourceBuilder.size(size);
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        // 条件投入
        // searchSourceBuilder.query(termQueryBuilder);
        searchSourceBuilder.query(boolQueryBuilder);
        // 3.添加条件到请求
        searchRequest.source(searchSourceBuilder);
        // 4.客户端查询请求
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
        // 5.查看返回结果
        SearchHits hits = search.getHits();
        System.out.println("hits: " + JSON.toJSONString(hits));
        System.out.println("=======================");
        for (SearchHit documentFields : hits.getHits()) {
            HighlightField highlightFieldContent = documentFields.getHighlightFields().get("content");
            if (highlightFieldContent != null) {
                StringBuilder buffer = new StringBuilder();
                for (Text fragment : highlightFieldContent.fragments()) {
                    buffer.append(fragment.string());
                }
                System.out.println("highlight: "  + buffer);
            }
            System.out.println("source: " + documentFields.getSourceAsMap());
        }
        System.out.println("total: " + hits.getTotalHits().value);
    }
}
